12. 集合工具类及文件操作

集合的工具类

数组的工具类:java.util.Arrays

集合的工具类:java.utils.Collections

addAll

作用是添加多个对象到集合中。参数类型为 (Collection<? super T>, T...) 即,第一个参数类型需要为 Collection 类型,或者父类为 Collection。第二个参数可以为多个。第二个参数需要和第一个参数的泛型类型相同。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.itguigu.com;

import java.util.ArrayList;
import java.util.Collections;

import org.junit.Test;

public class TestConlections {
@Test
public void name() {
ArrayList<String> arrayList = new ArrayList<>();
boolean addAll = Collections.addAll(arrayList, "a", "b", "c");
System.out.println(addAll); // true

for (String str : arrayList) {
System.out.println(str); // a b c
}
}
}

binarySearch

二分查找法,在 list 集合中查找 key 的索引。参数类型为 (List<? extends Comparable<? super T>>, T) 即,第一个参数为 List 类型,且需要实现 Comparable 或者父类实现了 Comparable。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.itguigu.com;

import java.util.ArrayList;
import java.util.Collections;

import org.junit.Test;

public class TestConlections {
@Test
public void name() {
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("a");
arrayList.add("b");

int binarySearch = Collections.binarySearch(arrayList, "b");
System.out.println(binarySearch); // 1
}
}

disjoint

判断两个集合是否有交集,没有则返回 true。参数类型为 Collection<?>, Collection<?>,即为两个 Collection,Collection 里面为任意类型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.itguigu.com;

import java.util.ArrayList;
import java.util.Collections;

import org.junit.Test;

public class TestConlections {
@Test
public void name() {
ArrayList<Object> arrayList = new ArrayList<>();
arrayList.add(1);
arrayList.add(2);

ArrayList<Object> arrayList2 = new ArrayList<>();
arrayList2.add("1");
arrayList2.add("2");

boolean disjoint = Collections.disjoint(arrayList, arrayList2);
System.out.println(disjoint); //true
}
}

max

寻找出集合中的最大值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package com.itguigu.com;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

import org.junit.Test;

class Student implements Comparable<Student>{
@Override
public int compareTo(Student o) {
return 0;
}
}

class Student2{}

public class TestConlections {
@Test
public void name() {
// 1: 自带实现了 Comparable 的类型
ArrayList<Integer> arrayList = new ArrayList<>();
arrayList.add(1);
arrayList.add(2);
Integer max = Collections.max(arrayList); //
System.out.println(max);

// 2: 自定义类,实现了 Comparable 接口
ArrayList<Student> arrayList2 = new ArrayList<>();
arrayList2.add(new Student());
arrayList2.add(new Student());
Student max2 = Collections.max(arrayList2);
System.out.println(max2);

// 3: max 方法接收第二个参数,第二个参数为匿名对象实现的比较器
ArrayList<Student2> arrayList3 = new ArrayList<>();
arrayList3.add(new Student2());
arrayList3.add(new Student2());
Collections.max(arrayList3, new Comparator<Student2>() {
@Override
public int compare(Student2 o1, Student2 o2) {
return 0;
}
});
}
}

sort

对 list 中的元素进行排序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package com.itguigu.com;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

import org.junit.Test;

class Student implements Comparable<Student>{
@Override
public int compareTo(Student o) {
return 0;
}
}

class Student2{}

public class TestConlections {
@Test
public void name() {
// 1: 自带实现了 Comparable 的类型
ArrayList<Integer> arrayList = new ArrayList<>();
arrayList.add(1);
arrayList.add(2);
Collections.sort(arrayList);

// 2: 自定义类,实现了 Comparable 接口
ArrayList<Student> arrayList2 = new ArrayList<>();
arrayList2.add(new Student());
arrayList2.add(new Student());
Collections.sort(arrayList2);

// 3: sort 方法接收第二个参数,第二个参数为匿名对象实现的比较器
ArrayList<Student2> arrayList3 = new ArrayList<>();
arrayList3.add(new Student2());
arrayList3.add(new Student2());
Collections.sort(arrayList3, new Comparator<Student2>() {
@Override
public int compare(Student2 o1, Student2 o2) {
return 0;
}
});
}
}

文件和目录

java.io.File 类是文件和目录路径的抽象表示形式。文件和目录都是用 的 File 对象表示。在 java 中,路径分割可以使用 / , \\, File.separator 表示。常用的为第一种。

getPath

构造器怎么指定,就是什么值

1
2
3
4
5
6
@Test
public void name() {
File file = new File("/Users/rex/Downloads/000JavaSe/day23_泛型和io流/day23_video/day23_06文件和目录:java.io.File类.avi");
System.out.println(file.getPath());
// /Users/rex/Downloads/000JavaSe/day23_泛型和io流/day23_video/day23_06文件和目录:java.io.File类.avi
}

getAbsolutePath

绝对路径

1
2
3
4
5
6
@Test
public void name2() {
File file = new File("../day23_泛型和io流/day23_video/day23_06文件和目录:java.io.File类.avi");
System.out.println(file.getAbsolutePath());
// /Users/rex/Documents/Projects/java/day23/../day23_泛型和io流/day23_video/day23_06文件和目录:java.io.File类.avi
}

getCanonicalPath

规范路径,会正确解析 ../ 为上级目录

1
2
3
4
5
6
@Test
public void name3() throws IOException {
File file = new File("../day23_泛型和io流/day23_video/day23_06文件和目录:java.io.File类.avi");
System.out.println(file.getCanonicalPath());
// /Users/rex/Documents/Projects/java/day23_泛型和io流/day23_video/day23_06文件和目录:java.io.File类.avi
}

getName

获取文件名称

1
2
3
4
5
6
@Test
public void name4() throws IOException {
File file = new File("../day23_泛型和io流/day23_video/day23_06文件和目录:java.io.File类.avi");
System.out.println(file.getName());
// day23_06文件和目录:java.io.File类.av
}

文件扩展名

1
2
3
4
5
6
7
8
9
@Test
public void name5() {
File file = new File("/Users/rex/Downloads/000JavaSe/day23_泛型和io流/day23_video/day23_06文件和目录:java.io.File类.avi");
String path = file.getPath();
int lastIndexOf = path.lastIndexOf(".");
String substring = path.substring(lastIndexOf);
System.out.println(substring);
// .avi
}

length

获取文件大小,单位为字节。不能获取文件夹的大小,否则返回值是一个不固定的值。

1
2
3
4
5
6
@Test
public void name6() {
File file = new File("/Users/rex/Downloads/000JavaSe/day23_泛型和io流/day23_video/day23_06文件和目录:java.io.File类.avi");
System.out.println(file.length());
// 139043672
}

lastModified

返回文件最后修改时间,格式为毫秒。

1
2
3
4
5
6
7
@Test
public void name7() {
File file = new File("/Users/rex/Downloads/000JavaSe/day23_泛型和io流/day23_video/day23_06文件和目录:java.io.File类.avi");
Date date = new Date(file.lastModified());
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:SS:MM");
System.out.println(simpleDateFormat.format(date));
}

getParent | getParentFile

获取父目录

1
2
3
4
5
6
@Test
public void name8() {
File file = new File("/Users/rex/Downloads/000JavaSe/day23_泛型和io流/day23_video/day23_06文件和目录:java.io.File类.avi");
String parent = file.getParent(); // 文件名称
File parentFile = file.getParentFile(); // file 类型
}

list | listFiles

获取下一级目录

1
2
3
4
5
6
@Test
public void name9() {
File file = new File("/Users/rex/Downloads/000JavaSe/day23_泛型和io流/day23_video/day23_06文件和目录:java.io.File类.avi");
String[] list = file.list(); // 文件名称
File[] listFiles = file.listFiles(); // file 类型
}

exists

判断是否存在

1
2
3
4
5
6
@Test
public void name10() {
File file = new File("/Users/rex/Downloads/000JavaSe/day23_泛型和io流/day23_video/day23_06文件和目录:java.io.File类.avi");
boolean exists = file.exists();
System.out.println(exists);
}

isFile

判断是否为文件

1
2
3
4
5
@Test
public void name11() {
File file = new File("/Users/rex/Downloads/000JavaSe/day23_泛型和io流/day23_video/day23_06文件和目录:java.io.File类.avi");
System.out.println(file.isFile());
}

isDirectory

判断是否为文件夹

1
2
3
4
5
@Test
public void name12() {
File file = new File("/Users/rex/Downloads/000JavaSe/day23_泛型和io流/day23_video/day23_06文件和目录:java.io.File类.avi");
System.out.println(file.isDirectory());
}

canRead

判断是否可读

1
2
3
4
5
@Test
public void name13() {
File file = new File("/Users/rex/Downloads/000JavaSe/day23_泛型和io流/day23_video/day23_06文件和目录:java.io.File类.avi");
System.out.println(file.canRead());
}

canWrite

判断是否可写

1
2
3
4
5
@Test
public void name14() {
File file = new File("/Users/rex/Downloads/000JavaSe/day23_泛型和io流/day23_video/day23_06文件和目录:java.io.File类.avi");
System.out.println(file.canWrite());
}

isHidden

判断是否隐藏

1
2
3
4
5
@Test
public void name15() {
File file = new File("/Users/rex/Downloads/000JavaSe/day23_泛型和io流/day23_video/day23_06文件和目录:java.io.File类.avi");
System.out.println(file.isHidden());
}

目录大小

使用递归将每个目录的文件大小进行相加。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.itguigu.com;

import java.io.File;

public class TestFile {
public static void main(String[] args) {
File filePath = new File("/Users/rex/Downloads/000JavaSe/day23_泛型和io流/day23_video/");
long length = getLength(filePath);
System.out.println(length);
}

public static long getLength(File filePath) {
if(filePath.isFile()) {
return filePath.length();
}else {
long size = 0;
File[] listFiles = filePath.listFiles();
for (File file : listFiles) {
size += getLength(file);
}
return size;
}
}
}

createNewFile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.itguigu.com;

import java.io.File;
import java.io.IOException;

import org.junit.Test;

public class TestCre {
@Test
public void test1() throws IOException {
File file = new File("/Users/rex/Downloads/000JavaSe/day23_泛型和io流/1.txt");
file.createNewFile();
}
}

mkdir

只能创建一级目录,如果有多级则不能创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.itguigu.com;

import java.io.File;
import java.io.IOException;

import org.junit.Test;

public class TestCre {
@Test
public void test1() throws IOException {
File file = new File("/Users/rex/Downloads/000JavaSe/day23_泛型和io流/new_dir");
file.mkdir();
}
}

mkdirs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.itguigu.com;

import java.io.File;
import java.io.IOException;

import org.junit.Test;

public class TestCre {
@Test
public void test1() throws IOException {
File file = new File("/Users/rex/Downloads/000JavaSe/day23_泛型和io流/new_dir/aaa/bbb/ccc");
file.mkdirs();
}
}

delete

能删除文件和空目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.itguigu.com;

import java.io.File;
import java.io.IOException;

import org.junit.Test;

public class TestCre {
@Test
public void test1() throws IOException {
File file = new File("/Users/rex/Downloads/000JavaSe/day23_泛型和io流/1.txt");
file.delete();
}
}

IO 流

字节(Byte):字节是通过网络传输信息(或在硬盘或内存中存储信息)的单位。字节是计算机信息技术用于计量存储容量和传输容量的一种计量单位,1个字节等于8位二进制,它是一个8位的二进制数,是一个很具体的存储空间。

字符:人们使用的记号,抽象意义上的一个符号。 ‘1’, ‘中’, ‘a’, ‘$’, ‘¥’, ……

我们可以简单的记这样一个结论:按照ANSI编码标准,标点符号、数字、大小写字母都占一个字节,汉字占2个字节。按照UNICODE标准所有字符都占2个字节。更多信息

字节流:以字节为单位,适用于所有类型的数据。字符流:以字符为单位,仅能处理纯文本(.java, .txt, .css, .js, .html)的数据。

以 Stream 结尾的都是和字节相关的流,以 Reader,Writer 结尾的都是和字符相关的流。

最基础的四个抽象类

  1. InputStream(字节输入流)
  2. OutputStream(字节输出流)
  3. Reader(字符输入流)
  4. Writer(字符输出流)

常见的 IO 流

1. 文件 IO 流
  1. FileInputStream,可以读取任意类型的文件
  2. FileOutputStream,可以把数据写到任意类型的文件
  3. FileReader, 只能读取纯文本的文件
  4. FileWriter, 只能把数据写到纯文本的文件
2. 缓冲流
  1. BufferedInputStream, 字节缓冲输入流,只能给 InputStream 系列的 IO 流增加缓冲功能

  2. BufferedOutputStream, 字节缓冲输出流, 只能给 OutputStream 系列的 IO 流增加缓冲功能

  3. BufferedReader,字符缓冲输入流,只能给 Reader 系列的 IO 流增加缓冲功能

  4. BufferedWriter,字符缓冲输出流,只能给 Writer 系列的 IO 流增加缓冲功能

3. 数据 IO 流
  1. DataInputStream,数据字节输入流
  2. DataOutputStream,数据字节输出流
4. 字符串 IO 流
  1. StringReader
  2. StringWriter
5. 数组 IO 流
  1. ByteArrayInputStream,从 byte[] 数组中读取
  2. ByteArrayOutputStream, 写入到 byte[] 数组中
  3. CharArrayReader,从 char[] 数组中读取
  4. CharArrayWriter, 写入到 char[] 数组中
6. 对象 IO 流
  1. ObjectInputStream,对象字节输入流, 反序列化流(把字节序列解析为 Java 对象)
  2. ObjectOutputStream,对象字节输出流,序列化(把 Java 对象转为字节序列)
7. 打印流
  1. PrintStream
  2. PrintWriter

读文件示例

FileInputStream

FileInputStream 中共有三个系列的读方法,分别是:

  1. Int read(): 一次读取一个字节,返回的是该字节的值
  2. int read(byte [] data): 一次读取多个字节,返回的是本次实际读取的字节的个数。并将结果存储在 data 字节 数组中。
  3. int read(byte [] data, int offset, int len): 一次读取多个字节,返回的是本次实际读取的字节的个数。并将结果存储在 data 字节数组中。可以指定从 byte 数组的哪个位置开始存储,并且可以指定存储长度 len。

这个三个方法的共同点都是如果读取不到数据,那么就返回 -1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package com.itguigu.com;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import javax.sound.sampled.LineListener;

import org.junit.Test;

public class TestReader {
@Test
public void read0() throws IOException {
FileInputStream fileInputStream = new FileInputStream("/Users/rex/1.txt");
// 一次读取一个字节
int read = fileInputStream.read();
System.out.print(read);
System.out.println("=====");
fileInputStream.close();
}

@Test
public void read1() throws IOException {
FileInputStream fileInputStream = new FileInputStream("/Users/rex/1.txt");
byte [] data = new byte[10];
// 一次读取多个字节,返回值为读取到的字节长度
int read = fileInputStream.read(data);
System.out.print(read);
// 转为字符串打印
System.out.print(new String(data));
System.out.println("=====");
fileInputStream.close();
}

@Test
public void read2() throws IOException {
FileInputStream fileInputStream = new FileInputStream("/Users/rex/1.txt");
byte [] data = new byte[10];
int len;
// 一次读取多个字节,返回值为读取到的字节长度,直到没有了数据返回
while ((len = fileInputStream.read(data))!=-1) {
// 这里很可能打印出乱码,因为每次读取10个字节,很可能将一个汉字拆成了两部分。
// 解决方法是使用 FileReader,读取到的是字符,就不怕被截取了
System.out.print(new String(data, 0 ,len));
}
fileInputStream.close();
}
}
FileReader
  1. Int read(): 一次读取一个字符,返回的是该字符的值
  2. int read(char [] data): 一次读取多个字符,返回的是本次实际读取的字符的个数。并将结果存储在 data 字符 数组中。
  3. int read(char [] data, int offset, int len): 一次读取多个字符,返回的是本次实际读取的字符的个数。并将结果存储在 data 字符数组中。可以指定从 char 数组的哪个位置开始存储,并且可以指定存储长度 len。

这个三个方法的共同点都是如果读取不到数据,那么就返回 -1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package com.itguigu.com;

import java.io.FileReader;
import java.io.IOException;
import org.junit.Test;

public class TestReader {
@Test
public void read0() throws IOException {
FileReader fileReader = new FileReader("/Users/rex/1.txt");
// 一次读取一个字符
int read = fileReader.read();
System.out.print(read);
System.out.println("=====");
fileReader.close();
}

@Test
public void read1() throws IOException {
FileReader fileReadere = new FileReader("/Users/rex/1.txt");
char [] data = new char[10];
// 一次读取多个字符,返回值为读取到的字符长度
int read = fileReadere.read(data);
System.out.print(read);
// 转为字符串打印
System.out.print(new String(data));
System.out.println("=====");
fileReadere.close();
}

@Test
public void read2() throws IOException {
FileReader fileReader = new FileReader("/Users/rex/1.txt");
char [] data = new char[10];
int len;
// 一次读取多个字符,返回值为读取到的字符长度,直到没有了数据返回
while ((len = fileReader.read(data))!=-1) {
System.out.print(new String(data, 0 ,len));
}
fileReader.close();
}
}

写文件示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package com.itguigu.com;

import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;

import org.junit.Test;

public class TestWrite {
@Test
public void test1() throws IOException {
String string = "飞流直下三千尺";
FileOutputStream fileOutputStream = new FileOutputStream("/Users/rex/1.txt")
fileOutputStream.write(string.getBytes()); // 写入字节数组
fileOutputStream.close();
}


@Test
public void test2() throws IOException {
String string = "飞流直下三千尺";
// 覆盖模式
FileWriter fileWriter = new FileWriter("/Users/rex/2.txt")
fileWriter.write(string); // 直接写入字符串
fileWriter.close();
}


@Test
public void test3() throws IOException {
String string = "飞流直下三千尺";
// 追加模式
FileWriter fileWriter = new FileWriter("/Users/rex/2.txt", true)
fileWriter.write(string); // 直接写入字符串
fileWriter.close();
}
}

复制文件

复制普通小文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.itguigu.com;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class TestCopyFile {
public static void main(String[] args) throws IOException {
CopyFile("/Users/2.txt", "/Users/3.txt");
}

public static void CopyFile(String srcPath, String destPath) throws IOException {
FileInputStream fileInputStream = new FileInputStream(srcPath);
FileOutputStream fileOutputStream = new FileOutputStream(destPath);

byte[] data = new byte[10];
int len;

// 边读边写
while ((len = fileInputStream.read(data)) != -1) {
// 这里必须使用下面的方法,不然最后一个写入可能会遗留上一次的内容
// fileOutputStream.write(data);
fileOutputStream.write(data, 0, len);
}

fileInputStream.close();
fileOutputStream.close();
}
}
复制大文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package com.itguigu.com;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class TestCopyFileBuffer {
public static void main(String[] args) throws IOException {
CopyFile("/Users/1.avi", "/Users/2.avi");
}

public static void CopyFile(String srcPath, String destPath) throws IOException {
// 比喻成穿衣服,先穿
FileInputStream fileInputStream = new FileInputStream(srcPath);
FileOutputStream fileOutputStream = new FileOutputStream(destPath);
// 比喻成穿衣服,后穿
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);

byte[] data = new byte[1024];
int len;

while ((len = bufferedInputStream.read(data)) != -1) {
// 这里必须使用下面的方法,不然最后一个写入可能会遗留上一次的内容
// fileOutputStream.write(data);
bufferedOutputStream.write(data, 0, len);
}

// 后穿的先脱
bufferedInputStream.close();
fileInputStream.close();
// 后穿的先脱
bufferedOutputStream.close();
fileOutputStream.close();
}
}

try…with…resources

传统的 try 结构如下:

1
2
3
4
5
6
7
8
资源声明,例如 IO 流
try{
...
}catch(异常类型 e){
...
}finally{
关闭资源
}

JDK 1.7 之后多了一种 try…with…resources 的形式,不用写 finally,资源使用完了会自动关闭。结构如下:

1
2
3
4
5
try(资源声明){
...
}catch(异常类型 e){
...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.itguigu.com;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;

public class TestCopyFileBuffer {
public static void main(String[] args) {
CopyFile("/Users/1.avi", "/Users/2.avi");
}

public static void CopyFile(String srcPath, String destPath){
try(
// 比喻成穿衣服,先穿
FileInputStream fileInputStream = new FileInputStream(srcPath);
FileOutputStream fileOutputStream = new FileOutputStream(destPath);
// 比喻成穿衣服,后穿
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
){
byte[] data = new byte[1024];
int len;
while ((len = bufferedInputStream.read(data)) != -1) {
// 这里必须使用下面的方法,不然最后一个写入可能会遗留上一次的内容
// fileOutputStream.write(data);
bufferedOutputStream.write(data, 0, len);
}
}catch (Exception e) {
e.printStackTrace();
}

}
}

格式转换

读取 UTF8 文件, 写入到 GBK 文件中

OutputStreamWriter,将字符流的数据 ———>按照指定编码———> 编码为字节流的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package com.itguigu.com;

import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;


public class TestEncode {
/**
* 字符串编码:字符串转换为字节数组,byte[] getBytes(xx)
* 字符串解码:字节数组转换为字符串,new String(byte[] xx)
* @throws IOException
*
*/
public static void main(String[] args) throws IOException {
// TestReadUTF8WriteGBK1()
TestReadUTF8WriteGBK2();
}

public static void TestReadUTF8WriteGBK1() throws IOException {
// 这种方式写入 gbk.txt 就是乱码,因为读取到的内容是 utf8 的(软件设置的编码就是 utf8)
FileReader fileReader = new FileReader("resources/utf8.txt");
FileWriter fileWriter = new FileWriter("resources/gbk.txt");

char [] data = new char[10];
int len;
while ((len=fileReader.read(data))!=-1) {
fileWriter.write(data, 0, len);
}
fileReader.close();
fileWriter.close();
}

public static void TestReadUTF8WriteGBK2() throws IOException {
// 这种方式是将字符流的数据 ----> 指定编码方式 ----> 字节流数据
FileReader fileReader = new FileReader("resources/utf8.txt");
FileOutputStream fileOutputStream = new FileOutputStream("resources/gbk.txt");
// 将字符流的数据按照指定编码方式转换为字节流数据
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, "GBK");

char [] data = new char[10];
int len;
while ((len=fileReader.read(data))!=-1) {
outputStreamWriter.write(data, 0, len);
}
fileReader.close();
outputStreamWriter.close();
fileOutputStream.close();
}
}
读取 GBK 文件

InputStreamReader

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.itguigu.com;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class TestReadGBKFile {
public static void main(String[] args) throws IOException {
// TestReadGBKFile1();
TestReadGBKFile2();
}

public static void TestReadGBKFile1() throws IOException {
// 方式1: 读取字节流数组,转为字符串的时候指定编码
FileInputStream fileInputStream = new FileInputStream("resources/gbk.txt");
int len;
byte[] data = new byte[10];

while ((len=fileInputStream.read(data))!=-1) {
System.out.print(new String(data, 0, len, "GBK"));
}
}

public static void TestReadGBKFile2() throws IOException {
// 方式2: 这种方式是将字节流的数据 ----> 指定编码方式 ----> 字符流数据
FileInputStream fileInputStream = new FileInputStream("resources/gbk.txt");
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "GBK");
int len;
char[] data = new char[10];

while ((len=inputStreamReader.read(data))!=-1) {
System.out.print(new String(data, 0, len));
}
}
}